package com.ikas.ai.server.module.instance.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikas.ai.server.module.instance.dao.WorkInstanceStepDetailCostDao;
import com.ikas.ai.server.module.instance.model.WorkFlowInstance;
import com.ikas.ai.server.module.instance.model.WorkInstanceStepDetail;
import com.ikas.ai.server.module.instance.model.WorkInstanceStepDetailCost;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WorkInstanceStepDetailCostService extends ServiceImpl<WorkInstanceStepDetailCostDao, WorkInstanceStepDetailCost> {

    @Autowired
    WorkInstanceStepService workInstanceStepService;
    @Autowired
    WorkFlowInstanceService workFlowInstanceService;
    @Autowired
    WorkInstanceStepDetailService workInstanceStepDetailService;


    @Value("${work-instance.step-detail.cost-time.max-length:100}")
    Integer maxStepDetailCostTimeLength;

    /**
     * @param machineNo
     * @param detail
     */
    @Transactional(rollbackFor = Exception.class)
    public void computeAvgCostTime(String machineNo, WorkInstanceStepDetail detail) {
        if (machineNo == null) {
            return;
        }
        WorkInstanceStepDetailCost one = getOne(
                new LambdaQueryWrapper<WorkInstanceStepDetailCost>()
                        .eq(WorkInstanceStepDetailCost::getMachineNo, machineNo)
                        .eq(WorkInstanceStepDetailCost::getWfName, detail.getWfName())
                        .eq(WorkInstanceStepDetailCost::getStepName, detail.getStepName())
                        .eq(WorkInstanceStepDetailCost::getMeteCode, detail.getMeteCode())
        );
        /**
         * 如果为空，新建一个对象，并新建一个数组并放入当前delay时间
         */
        if (one == null) {
            one = new WorkInstanceStepDetailCost().setMachineNo(machineNo).setWfName(detail.getWfName()).setStepName(detail.getStepName()).setMeteCode(detail.getMeteCode());
            List<Long> costTimeArray = new ArrayList<>();
            costTimeArray.add(detail.getCostTime());
            one.setCostTimeArray(costTimeArray);
            one.setAvgCostTime(detail.getCostTime());
        } else {
            one = dealWithCostTime(detail.getCostTime(), one);
            one.setUpdateTime(new Date());
        }
        save(one);
        //更新detail表平均耗时
        detail.setAvgCostTime(one.getAvgCostTime());
        detail.setUpdateTime(new Date());
        workInstanceStepDetailService.updateById(detail);
    }

    private WorkInstanceStepDetailCost dealWithCostTime(Long delay, WorkInstanceStepDetailCost one) {
        if (delay == null) {
            return one;
        }
        if (one.getCostTimeArray() == null) {
            one.setCostTimeArray(new ArrayList<>());
        }
        LinkedList<Long> costTimeArray = new LinkedList<>(one.getCostTimeArray());
        if (costTimeArray.size() < maxStepDetailCostTimeLength) {
            //DO NOTHING
            costTimeArray.addFirst(delay);
        } else if (costTimeArray.size() > maxStepDetailCostTimeLength) {
            Integer defaultSize = costTimeArray.size();
            for (int k = 0; k <= defaultSize - maxStepDetailCostTimeLength; k++) {
                costTimeArray.pollLast();
            }
            costTimeArray.addFirst(delay);
        } else {
            costTimeArray.removeLast();
            costTimeArray.addFirst(delay);
        }
        one.setCostTimeArray(costTimeArray);
        Long sum = 0L;
        for (Long costTimeElement : costTimeArray) {
            sum += costTimeElement;
        }
        Long avgCostTime = 0L;
        if (sum != 0L) {
            avgCostTime = sum / costTimeArray.size();
        }
        one.setAvgCostTime(avgCostTime);
        return one;
    }

    public void putExistStepDetailCostTimeIntoTable() {
        List<WorkFlowInstance> workFlowInstances = workFlowInstanceService.list();
        Map<Long, String> machineNoCollect = workFlowInstances.stream().collect(Collectors.toMap(
                WorkFlowInstance::getId,
                WorkFlowInstance::getMachineNo
        ));
        List<WorkInstanceStepDetailCost> detailCosts = new ArrayList<>();
        List<WorkInstanceStepDetail> detailsList = workInstanceStepDetailService.list();
        Map<Long, List<WorkInstanceStepDetail>> detailMap = detailsList.stream().collect(Collectors.groupingBy(WorkInstanceStepDetail::getDetailId));
        log.info("=---开始初始化，共有WorkInstanceStep {} 个,属于 {} 个Condition--=", detailsList.size(), detailMap.keySet().size());
        Integer countFlag = 0;
        for (Long detailId : detailMap.keySet()) {
            countFlag += 1;
            log.info("===============>开始处理第{}个=================>", countFlag);
            List<WorkInstanceStepDetail> childDetailList = detailMap.get(detailId);
            if (CollectionUtils.isEmpty(detailsList)) {
                continue;
            }
            WorkInstanceStepDetail workInstanceStepDetail = childDetailList.get(0);
            String machineNo = machineNoCollect.get(workInstanceStepDetail.getWfInstanceId());
            if (machineNo == null) {
                continue;
            }
            String wfName = workInstanceStepDetail.getWfName();
            String meteCode = workInstanceStepDetail.getMeteCode();
            String stepName = workInstanceStepDetail.getStepName();
            WorkInstanceStepDetailCost WorkInstanceStepDetailCost = new WorkInstanceStepDetailCost().setStepName(stepName).setWfName(wfName).setMachineNo(machineNo).setMeteCode(meteCode);
            log.info("=-----开始处理工况{}，步骤名为{}的步骤，下属步骤实例{}个----=", wfName, stepName, childDetailList.size());
            Long sum = 0L;
            List<Long> costTimeArray = new ArrayList<>();
            for (WorkInstanceStepDetail detail : childDetailList) {
                if (costTimeArray.size() <= maxStepDetailCostTimeLength) {
                    Long costTime = detail.getCostTime();
                    if (costTime == null) {
                        continue;
                    }
                    sum += costTime;
                    costTimeArray.add(costTime);
                } else {
                    break;
                }
            }
            Long avgCostTime = 0L;
            if (sum != 0L) {
                avgCostTime = sum / costTimeArray.size();
            }
            WorkInstanceStepDetailCost.setCostTimeArray(costTimeArray);
            WorkInstanceStepDetailCost.setAvgCostTime(avgCostTime);
            log.info("=-----最终结果，平均时间为：{},整体数组为：{}----=", avgCostTime, costTimeArray);
            detailCosts.add(WorkInstanceStepDetailCost);
        }
        detailCosts = detailCosts.stream().filter(bean -> bean.getMeteCode() != null).distinct().collect(Collectors.toList());
        saveBatch(detailCosts);

    }
}
